終於進到實作環節啦——
之前在Codrops曾看到用React Three Fiber做出酷炫3D效果的案例,就想說一定要趁著鐵人賽嘗試。
這次參考的程式碼中出現了interface Props,而這其實是TypeScript的語法。雖說日後若真的靠前端糊口飯吃,我想會有很高的機率寫到TS,不過這邊還是先以JS為主,找時間再深造TypeHero。
打鐵趁熱,首先自然要載three和@react-three/fiber。
此時的畫面沒占滿,所以到CSS設定main的大小。
接著導入Canvas。
// App.js
import { Canvas } from "@react-three/fiber";
import Ring from "./ring";
import "./styles.css";
export default function App() {
return (
<main>
<Canvas>
<Ring radius={2} height={4} segments={32} />
</Canvas>
</main>
);
}
// ring.js
export default function Ring({ radius, height, segments }) {
return (
<mesh>
<cylinderGeometry args={[radius, radius, height, segments]} />
<meshBasicMaterial />
</mesh>
);
}
很好,我們有個圓柱體了。
這時為了上字,就要來引入,和R3F同樣由Poimandres開發的超強外掛drei。
// App.js
// 加上測試用的text
<Ring
radius={2}
height={4}
segments={32}
text="X X X X X X X X X X X X X X X X X X X X X X X X X X X X "
/>
// ring.js
import { Text } from "@react-three/drei";
export default function Ring({ text = "", radius, height, segments }) {
const textPositions = [];
const angleStep = (2 * Math.PI) / text.length;
for (let i = 0; i < text.length; i++) {
const angle = i * angleStep;
const x = radius * Math.cos(angle);
const z = radius * Math.sin(angle);
textPositions.push({ x, z });
}
}
這裡有些小細節可以注意:
像是text如果沒先預設成空字串會沒辦法讀它的length。
另一個小卡關的是要const textPositions = [],不能設成 [0, 0]。
// ring.js
return (
<group>
<mesh>
<cylinderGeometry args={[radius, radius, height, segments]} />
<meshBasicMaterial />
</mesh>
{text.split("").map((char, index) => (
<Text
key={index}
position={[textPositions[index].x, 0, textPositions[index].z]}
rotation={[0, -angleStep * index + Math.PI / 2, 0]}
fontSize={0.3}
lineHeight={1}
letterSpacing={0.02}
color="white"
textAlign="center"
>
{char}
</Text>
))}
</group>
);
現在圓柱體外有字了。
一起用useRef + useFrame(R3F的Hook),來讓畫面轉起來。
// ring.js
const ref = useRef();
useFrame(() => {
ref.current.rotation.x += 0.01;
ref.current.rotation.y += 0.01;
ref.current.rotation.z += 0.01;
});
記得也要幫group加上ref喔。
再來把<meshBasicMaterial />
換成<MeshTransmissionMaterial/>
,就行啦。
透射材質讓整個頁面都高級起來了呢。
但學習不能只停留在複刻大神的心血,更要向外延伸。
而摸索和試錯也正是寫程式最令人煩躁、也最令人滿足的時光。
加入自己很喜歡、可以讓使用者自由轉動場景的基本功能<OrbitControls />
後,一時間我最想做的更動即是調整字型,沒料到想來簡單的課題卻耗了段時間。